angular.module('smart-table')
.directive('pageSelect', function () {
    return {
        restrict: 'E',
        template: '<input type="text" class="select-page" ng-model="inputPage" ng-change="selectPage(inputPage)">',
        link: function (scope, element, attrs) {
            scope.$watch('currentPage', function (c) {
                scope.inputPage = c;
            });
        }
    }
})
.directive('stSelectDistinct', [function () {
    return {
        restrict: 'E',
        require: '^stTable',
        scope: {
            collection: '=',
            predicate: '@',
            predicateExpression: '='
        },
        template: '<select class="filter-select" ng-model="selectedOption" ng-change="optionChanged(selectedOption)" ng-options="opt for opt in distinctItems"></select>',        
        link: function (scope, element, attr, table) {
            var getPredicate = function () {
                var predicate = scope.predicate;
                if (!predicate && scope.predicateExpression) {
                    predicate = scope.predicateExpression;
                }
                return predicate;
            }

            scope.$watch('collection', function (newValue) {
                var predicate = getPredicate();

                if (newValue) {
                    var temp = [];
                    scope.distinctItems = ['All'];

                    angular.forEach(scope.collection, function (item) {
                        var value = item[predicate];

                        if (value && value.trim().length > 0 && temp.indexOf(value) === -1) {
                            temp.push(value);
                        }
                    });
                    temp.sort();

                    scope.distinctItems = scope.distinctItems.concat(temp);
                    scope.selectedOption = scope.distinctItems[0];
                    scope.optionChanged(scope.selectedOption);
                }
            }, true);

            scope.optionChanged = function (selectedOption) {
                var predicate = getPredicate();

                var query = {};

                query.distinct = selectedOption;

                if (query.distinct === 'All') {
                    query.distinct = '';
                }

                table.search(query, predicate);
            };
        }
    }
}])
.directive('stSelectMultiple', function () {
    return {
        restrict: 'E',
        require: '^stTable',        
        scope: {
            collection: '=',
            predicate: '@',
            predicateExpression: '='
        },
        templateUrl: 'templates/stSelectMultiple.html',
        link: function (scope, element, attr, table) {
            scope.dropdownLabel = '';
            scope.filterChanged = filterChanged;

            scope.$watch('collection', function () {
                if (scope.collection)
                    initialize();
            });

            function initialize() {
                console.log("stSelectMultiple");
                bindCollection(scope.collection);
            }

            function getPredicate() {
                var predicate = scope.predicate;
                if (!predicate && scope.predicateExpression) {
                    predicate = scope.predicateExpression;
                }
                return predicate;
            }

            function getDropdownLabel() {
                var allCount = scope.distinctItems.length;

                var selected = getSelectedOptions();

                if (allCount === selected.length || selected.length === 0) {
                    return 'All';
                }

                if (selected.length === 1) {
                    return selected[0];
                }

                return selected.length + ' items';
            }

            function getSelectedOptions() {
                var selectedOptions = [];

                angular.forEach(scope.distinctItems, function (item) {
                    if (item.selected) {
                        selectedOptions.push(item.value);
                    }
                });

                return selectedOptions;
            }

            function bindCollection(collection) {
                var predicate = getPredicate();
                var distinctItems = [];

                angular.forEach(collection, function (item) {
                    var value = item[predicate];
                    fillDistinctItems(value, distinctItems);
                });

                distinctItems.sort(function (obj, other) {
                    if (obj.value > other.value) {
                        return 1;
                    } else if (obj.value < other.value) {
                        return -1;
                    }
                    return 0;
                });

                scope.distinctItems = distinctItems;

                filterChanged();
            }

            function filterChanged() {
                scope.dropdownLabel = getDropdownLabel();

                var predicate = getPredicate();

                var query = {
                    matchAny: {}
                };

                query.matchAny.items = getSelectedOptions();
                var numberOfItems = query.matchAny.items.length;
                if (numberOfItems === 0 || numberOfItems === scope.distinctItems.length) {
                    query.matchAny.all = true;
                } else {
                    query.matchAny.all = false;
                }

                table.search(query, predicate);
            }

            function fillDistinctItems(value, distinctItems) {
                if (value && value.trim().length > 0 && !findItemWithValue(distinctItems, value)) {
                    distinctItems.push({
                        value: value,
                        selected: true
                    });
                }
            }

            function findItemWithValue(collection, value) {
                var found = _.find(collection, function (item) {
                    return item.value === value;
                });

                return found;
            }
        }
    }
})
.directive('stNumberRange', ['$timeout', function ($timeout) {
    return {
        restrict: 'E',
        require: '^stTable',
        scope: {
            lower: '=',
            higher: '='
        },
        templateUrl: 'templates/stNumberRange.html',
        link: function (scope, element, attr, table) {
            var inputs = element.find('input');
            var inputLower = angular.element(inputs[0]);
            var inputHigher = angular.element(inputs[1]);
            var predicateName = attr.predicate;

            [inputLower, inputHigher].forEach(function (input, index) {

                input.bind('blur', function () {
                    var query = {};

                    if (scope.lower) {
                        query.lower = scope.lower;
                    }

                    if (scope.higher) {
                        query.higher = scope.higher;
                    }

                    scope.$apply(function () {
                        table.search(query, predicateName)
                    });
                });
            });
        }
    };
}])
.directive('stDateRange', ['$timeout', function ($timeout) {
    return {
        restrict: 'E',
        require: '^stTable',
        scope: {
            before: '=',
            after: '='
        },
        templateUrl: 'templates/stDateRange.html',

        link: function (scope, element, attr, table) {

            var inputs = element.find('input');
            var inputBefore = angular.element(inputs[0]);
            var inputAfter = angular.element(inputs[1]);
            var predicateName = attr.predicate;


            [inputBefore, inputAfter].forEach(function (input) {

                input.bind('blur', function () {


                    var query = {};

                    if (!scope.isBeforeOpen && !scope.isAfterOpen) {

                        if (scope.before) {
                            query.before = scope.before;
                        }

                        if (scope.after) {
                            query.after = scope.after;
                        }

                        scope.$apply(function () {
                            table.search(query, predicateName);
                        })
                    }
                });
            });

            function open(before) {
                return function ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();

                    if (before) {
                        scope.isBeforeOpen = true;
                    } else {
                        scope.isAfterOpen = true;
                    }
                }
            }

            scope.openBefore = open(true);
            scope.openAfter = open();
        }
    }
}])
.directive('stEditableField', ['QuoteServices', '$compile', function (QuoteServices, $compile) {
    var getTemplate = function (scope) {
        switch (scope.type) {
            case 'date':
                scope.ngModel = stringToDate(scope.ngModel);
                return "<a class='editable-column' uib-popover-template='dynamicPopover.templateUrl' popover-is-open='isOpen'><span>{{ngModel | date:'dd MMM yyyy'}}</span></a>";

            default: return "<a class='editable-column' uib-popover-template='dynamicPopover.templateUrl' popover-is-open='isOpen'>{{ngModel || 'edit'}}</a>";
        }
    }

    var stringToDate = function (dateStr) {
        var dateOnly = dateStr.split(" ")[0];
        var m = parseInt(dateOnly.split('/')[0]) - 1;
        var d = parseInt(dateOnly.split('/')[1]);
        var y = parseInt(dateOnly.split('/')[2]);

        return Date.UTC(y, m, d);
    };

    var dateToString = function (dateObj) {      

        var m = dateObj.getMonth() + 1;
        var d = dateObj.getDate();
        var y = dateObj.getFullYear();

        return m + "/" + d + "/" + y + " 00:00:00 AM";
    }

    return {
        restrict: 'E',
        require: '^stTable',
        scope: {
            ngModel: "=ngModel",
            row: "=row",
            type: "@type"
        },
        //template: function(scope){
        //    if (scope.type == 'date') {
        //        "<a class='editable-column' uib-popover-template='dynamicPopover.templateUrl' popover-is-open='isOpen'><span>{{ngModel | date:'dd MMM yyyy'}}</span></a>";
        //    } else
        //        return "<a class='editable-column' uib-popover-template='dynamicPopover.templateUrl' popover-is-open='isOpen'>{{ngModel || 'edit'}}</a>";
        //},   //ng-class='{'editable-empty': !ngModel.length}'
        replace: true,
        link: function (scope, element, attrs, ngModel, ctrl) {
            
            var el = $compile(getTemplate(scope))(scope);
            el.bind('click', function (e) {
                e.stopPropagation();
            });
            element.replaceWith(el);           
          

            scope.dynamicPopover = {
                templateUrl: 'templates/stEditableField.html',
                ngModel: scope.ngModel,
                fldType: attrs.type || 'text',               
                initField: function (event) {
                    event.stopPropagation();
                },
                update: function (event) {
                    // if (editfieldform.$valid) {
                    event.stopPropagation();
                   
                    switch (attrs.type) {
                        case "select":
                           
                            if (attrs.name.indexOf('MAINTENANCE_ITEM') != -1) {
                                //convert from name to key and update both name and key in the model 
                                scope.ngModel = scope.dynamicPopover.ngModel;

                                for (var i = 0; i < scope.dynamicPopover.options.length; i++)
                                    if (scope.dynamicPopover.options[i].VALUE == scope.dynamicPopover.ngModel) {
                                        scope.$parent.QC.changeLines(scope.dynamicPopover.options[i], attrs.name, scope.$parent.$index);
                                    }
                            }
                            break;
                        case "date":
                            scope.ngModel = dateToString(scope.dynamicPopover.ngModel);
                            scope.$parent.QC.changeLines(scope.dynamicPopover.ngModel, attrs.name, scope.$parent.$index);
                            break;

                        default:
                            scope.ngModel = scope.dynamicPopover.ngModel;
                            scope.$parent.QC.changeLines(scope.dynamicPopover.ngModel, attrs.name, scope.$parent.$index);
                            break;
                    }

                    scope.isOpen = false;

                },
                close: function (event) {
                    event.stopPropagation();
                    scope.isOpen = false;
                }
            };

            //load select options
            if (attrs.type == 'select') {
                if (attrs.name.indexOf('MAINTENANCE_ITEM') != -1) {
                    //load maintenance items
                    QuoteServices.getMaintenanceItems(scope.row.TOP_DIVISION)
                       .$promise
                       .then(function (results) {
                           scope.dynamicPopover.options = results;
                       })
                       .catch(function (response) { notifications.showError("MAINTENANCE_ITEMS load failed"); });
                }
            }
        }
    }

}])
//.directive('stEditableDate', function () {
//    return {
//        restrict: 'E',
//        require: '^stTable',
//        scope: {
//            ngModel: "=ngModel",
//        },
//        template: "<a class='editable-column' uib-popover-template='dynamicPopover.templateUrl' popover-is-open='isOpen'>{{ngModel | date:'dd MMM yyyy'}}</a>",
//        replace: true,
//        link: function (scope, element, attrs, ngModel) {
//            element.bind('click', function (e) {
//                e.stopPropagation();
//            });

//            scope.dynamicPopover = {
//                templateUrl: 'templates/stEditableField.html',
//                ngModel: scope.ngModel,
//                fldType: attrs.type || 'text',
//                min: attrs.min,
//                max: attrs.max,
//                initField: function (event) {
//                    event.stopPropagation();
//                },
//                update: function (event) {
//                    // if (editfieldform.$valid) {
//                    event.stopPropagation();
//                    scope.ngModel = scope.dynamicPopover.ngModel;
//                    scope.$parent.QC.changeLines(scope.dynamicPopover.ngModel, attrs.name, scope.$parent.$index);
//                    scope.isOpen = false;
//                    // }

//                },
//                close: function (event) {
//                    event.stopPropagation();
//                    scope.isOpen = false;
//                }
//            };
//        }
//    }
//})
.directive('stringToDate', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function (dateStr) {
                return '' + dateStr;
            });
            ngModel.$formatters.push(function (dateStr) {
                if (dateStr) {
                    var dateOnly = dateStr.split(" ")[0];
                    var m = parseInt(dateOnly.split('/')[0]) - 1;
                    var d = parseInt(dateOnly.split('/')[1]);
                    var y = parseInt(dateOnly.split('/')[2]);

                    return Date.UTC(y, m, d);
                }
            });
        }
    };
})


.directive('stFilterCustomIcon', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        scope:{            
            name:'='
        },
        link: function (scope, element, attrs) {
            var el = $compile("<span><i name='$parent.name' ng-click='showDiv = !showDiv' class='glyphicon glyphicon-filter'></i></span>")(scope);
            el.bind('click', function (e) {
                e.stopPropagation();
                var elm = el.$parent;
                scope.$apply(function () {
                    if (scope.$parent.QC.showDiv = scope.showDiv) {
                        scope.$parent.QC.showDiv = scope.showDiv
                    }
                    else
                        scope.$parent.QC.showDiv = !scope.showDiv;                    
                });
            });
            element.append(el);            
        }
    }
}])
//.directive('stFilterCustom', function () {
//    return {
//        restrict: 'E',
//        scope: {
//            predicate: "="
//        },
//        template: "<span class='filterable-column' uib-popover-template='dynamicPopover.templateUrl' popover-is-open='isOpen'><i class='glyphicon glyphicon-filter'></i></span>",
//        link: function(scope, element, attrs){
//            ////element.on('click', function(e){
//            ////    //e.stopPropagation();

//            ////});
//                //.append("<span class='filterable-column'><i class='glyphicon glyphicon-filter'></i></span>")
//                //.children('.filterable-column').on('click', function (e) {
//                //    e.stopPropagation();                    
//                //});

//            scope.dynamicPopover = {
//                templateUrl: 'templates/Filter.html',
//                selectedPredicate: scope.predicate,
//                update: function () {
//                    //scope.ngModel = scope.dynamicPopover.ngModel;
//                    //scope.$parent.quoteCtrl.changeLines(scope.dynamicPopover.ngModel, attrs.name, scope.$parent.$index);
//                    scope.isOpen = false;
//                },
//                close: function () {
//                    scope.isOpen = false;
//                }
//            };
//        }
//    }
//})
.filter('customFilter', ['$filter', function ($filter) {
    var filterFilter = $filter('filter');
    var standardComparator = function standardComparator(obj, text) {
        text = ('' + text).toLowerCase();
        return ('' + obj).toLowerCase().indexOf(text) > -1;
    };

    return function customFilter(array, expression) {
        function customComparator(actual, expected) {

            var isBeforeActivated = expected.before;
            var isAfterActivated = expected.after;
            var isLower = expected.lower;
            var isHigher = expected.higher;
            var higherLimit;
            var lowerLimit;
            var itemDate;
            var queryDate;

            if (angular.isObject(expected)) {
                //exact match
                if (expected.distinct) {
                    if (!actual || actual.toLowerCase() !== expected.distinct.toLowerCase()) {
                        return false;
                    }

                    return true;
                }

                //matchAny
                if (expected.matchAny) {
                    if (expected.matchAny.all) {
                        return true;
                    }

                    if (!actual) {
                        return false;
                    }

                    for (var i = 0; i < expected.matchAny.items.length; i++) {
                        if (actual.toLowerCase() === expected.matchAny.items[i].toLowerCase()) {
                            return true;
                        }
                    }

                    return false;
                }

                //date range
                if (expected.before || expected.after) {
                    try {
                        if (isBeforeActivated) {
                            higherLimit = expected.before;

                            itemDate = new Date(actual);
                            queryDate = new Date(higherLimit);

                            if (itemDate > queryDate) {
                                return false;
                            }
                        }

                        if (isAfterActivated) {
                            lowerLimit = expected.after;


                            itemDate = new Date(actual);
                            queryDate = new Date(lowerLimit);

                            if (itemDate < queryDate) {
                                return false;
                            }
                        }

                        return true;
                    } catch (e) {
                        return false;
                    }

                } else if (isLower || isHigher) {
                    //number range
                    if (isLower) {
                        higherLimit = expected.lower;

                        if (actual > higherLimit) {
                            return false;
                        }
                    }

                    if (isHigher) {
                        lowerLimit = expected.higher;
                        if (actual < lowerLimit) {
                            return false;
                        }
                    }

                    return true;
                }
                //etc

                return true;

            }
            return standardComparator(actual, expected);
        }

        var output = filterFilter(array, expression, customComparator);
        return output;
    };
}])
.filter('myStrictFilter', ['$filter', function ($filter) {
    return function (input, predicate) {      
        return $filter('filter')(input, predicate, true);
    }
}])
.filter('unique', function () {
    return function (arr, field) {        
        if (arr) {
            var o = {}, i, l = arr.length, r = [];
            for (i = 0; i < l; i += 1) {
                o[arr[i][field]] = arr[i];
            }
            for (i in o) {
                r.push(o[i]);
            }
            return r;
        } else {
            return null;
        }        
    };
});